package com.education.service;

import com.alibaba.fastjson.util.TypeUtils;
import com.education.common.model.AdminUserSession;
import com.education.common.utils.ObjectUtils;
import com.education.common.utils.Result;
import com.education.common.utils.ResultCode;
import com.education.common.utils.SpringBeanManager;
import com.education.mapper.BaseMapper;
import com.education.service.task.TaskManager;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.session.RowBounds;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 余一
 * @Description
 * @date 2021/7/1 11:40
 */
public abstract class BaseService<M extends BaseMapper> {
    private final String DEFAULT_METHOD = "queryList";
    @Autowired
    protected M mapper;

    @Autowired
    protected TaskManager taskManager;

    public Result pagination(Map params,Class<? extends BaseMapper> mapperClass,String methodName){
      try{
          Integer offset = RowBounds.NO_ROW_OFFSET;
          Integer limit = RowBounds.NO_ROW_LIMIT;
          if (ObjectUtils.isNotEmpty(params.get("offset"))) {
              offset = Integer.parseInt((String) params.get("offset"));
          }
          if (ObjectUtils.isNotEmpty(params.get("limit"))) {
              limit = Integer.parseInt((String) params.get("limit"));
          }
          Page<Object> page = PageHelper.offsetPage(offset, limit);
          Object pageResult = null;
          if (ObjectUtils.isNotEmpty(mapperClass)) {
              Method method = mapperClass.getMethod(methodName, Map.class);
              BaseMapper mapper = SpringBeanManager.getBean(mapperClass);
              pageResult = method.invoke(mapper,params);
          }else {
              pageResult =  mapper.queryList(params);
          }
          HashMap<String, Object> resultMap = new HashMap<>();
          resultMap.put("dataList",pageResult);
          resultMap.put("total",page.getTotal());
          return Result.success(resultMap);
      }catch (Exception e){
        logger.error("分页异常");
      }
      return Result.fail();
    }

    public Result pagination(Map params){
       return pagination(params,null,DEFAULT_METHOD);
    }

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 获取管理员用户信息
     * @return
     */
    public AdminUserSession getAdminUserSession(){
        Subject subject = SecurityUtils.getSubject();
        AdminUserSession userSession = (AdminUserSession) subject.getPrincipal();
        if (ObjectUtils.isNotEmpty(userSession)){
            return userSession;
        }
        return null;
    }

    public Result saveOrUpdate(Map dataMap){
        Integer id = (Integer) dataMap.get("id");
        Boolean updateFlag = false;
        if (ObjectUtils.isNotEmpty(id)){
            updateFlag = true;
        }
        return this.saveOrUpdate(updateFlag,dataMap);
    }

    private Result saveOrUpdate(Boolean updateFlag, Map modelBeanMap) {
        try {
            String msg = "";
            if (updateFlag) {
                this.checkParams(modelBeanMap);
                this.update(modelBeanMap);
                msg = "修改";
            }else {
                modelBeanMap.put("create_date",new Date());
                this.save(modelBeanMap);
                msg = "添加";
            }
            return Result.success(ResultCode.SUCCESS,msg + "成功");
        }catch (Exception e){
            logger.error("操作异常",e);
        }
        return Result.fail(ResultCode.FAIL,"操作异常");
    }

    protected void checkParams(Map params){
        if (params != null) {
            params.remove("create_date");
            params.remove("last_login_time");
        }
    }

    public int save(Map modelMap){
        HashMap params = new HashMap();
        params.put("params",modelMap);
        int result = mapper.save(params);
        Object id = params.get("id");
        // 如果主键id不为空的话，直接返回主键id
        if (ObjectUtils.isNotEmpty(id)) {
            return TypeUtils.castToInt(id);
        }
        return result;
    }

    public int update(Map modelMap){
        return mapper.update(modelMap);
    }

    public Result deleteById(Map modelMap){
        return deleteById((Integer) modelMap.get("id"));
    }

    public  Result deleteById(Integer id){
        int i = mapper.deleteById(id);
        if (i>0) {
            return Result.success(ResultCode.SUCCESS,"删除成功");
        }
        return Result.fail(ResultCode.FAIL,"删除失败");
    }

    /**
     * 更新shiro 缓存中的用户信息，避免由于redis 缓存导致获取用户信息不一致问题
     * @param adminUserSession
     */
    public void updateShiroCacheUserInfo(AdminUserSession adminUserSession) {
        Subject subject = SecurityUtils.getSubject();
        PrincipalCollection principals = subject.getPrincipals();
        //realName认证信息的key，对应的value就是认证的user对象
        String realName = principals.getRealmNames().iterator().next();
        //创建一个PrincipalCollection对象
        PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(adminUserSession, realName);
        // 调用subject的runAs方法，把新的PrincipalCollection放到session里面
        subject.runAs(newPrincipalCollection);
    }

}
